/* =========================================================================*
 * LoadBMPImage - Loads a BMP file and creates a bitmap GDI object
 *                also creates logical palette for it.
 * Returns      - TRUE for success   (check success or not)
 * sBMPFile     - Full path of the BMP file, (input file name)
 * bitmap       - The bitmap object to initialize, (bring back img in it)
 * pPal         - Will hold the logical palette. Can be NULL (bring back)
 *==========================================================================*/

BOOL CVPICDoc::LoadBMPImage(LPCTSTR sBMPFile, CBitmap &bitmap, CPalette *pPal)
{

        BITMAPFILEHEADER bmfHeader;

        // Read file header

        CFile file;
        if( !file.Open( sBMPFile, CFile::modeRead) ) return FALSE;

  if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
                return FALSE;

        // Check File type should be 'BM'
        if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
                return FALSE;

  read_bmp_o = bmfHeader.bfOffBits / 8;

        // Get length of the remainder of the file and allocate memory
        DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER);
        HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
        if (hDIB == 0)
                return FALSE;

        // Read the remainder of the bitmap file.
  // BITMAPINFOHEADER + possible-Color-Table + DIB-bits
        if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen )
        {
                ::GlobalFree(hDIB);
                return FALSE;
        }


        BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
        BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;

  read_bmp_w = bmiHeader.biWidth;
  read_bmp_h = bmiHeader.biHeight;
  read_bmp_c = bmiHeader.biBitCount;
        read_bmp_size = bmiHeader.biSizeImage;
  if (read_bmp_size == 0) {
   read_bmp_size = ((((read_bmp_w * read_bmp_c) + 31) & ~31) >> 3) * read_bmp_h;
  };
        read_bmp_l = read_bmp_size / read_bmp_h;   // scan line width

        // If bmiHeader.biClrUsed is zero we have to infer the number
        // of colors from the number of bits used to specify it.
        int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 
                                                1 << bmiHeader.biBitCount;

        LPVOID lpDIBBits;
        if( bmInfo.bmiHeader.biBitCount > 8 )
                lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + 
                        ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
        else
                lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);

        // Create the logical palette
        if( pPal != NULL )
        {
        // Create the palette
           if( nColors <= 256 )
            {
            UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
            LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

            pLP->palVersion = 0x300;
            pLP->palNumEntries = nColors;

            for( int i=0; i < nColors; i++)
            {
            pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
            pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
            pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
            pLP->palPalEntry[i].peFlags = 0;
            }

            pPal->CreatePalette( pLP );

            delete[] pLP;
                }
        }

        CClientDC dc(NULL);
        CPalette* pOldPalette = NULL;
        if( pPal )
        {
         pOldPalette = dc.SelectPalette( pPal, FALSE );
         dc.RealizePalette();
        }

        HBITMAP hBmp = CreateDIBitmap( dc.m_hDC,// handle to device context 
                                &bmiHeader,     // pointer to BITMAPINFOHEADER
                                CBM_INIT,       // initialization flag 
                                lpDIBBits,      // pointer to initialization data 
                                &bmInfo,        // pointer to bitmap color-format data 
                                DIB_RGB_COLORS);                // color-data usage 
        bitmap.Attach( hBmp );

        if( pOldPalette )
                dc.SelectPalette( pOldPalette, FALSE );

        ::GlobalFree(hDIB);
        return TRUE;

} 